package cn.sc.summer.mybatis.strategy.basestage;

import cn.hutool.core.collection.CollUtil;
import cn.sc.summer.mybatis.constant.TableColumnConstant;
import cn.sc.summer.mybatis.constant.TableResource;
import cn.sc.summer.mybatis.table.datasource.DataSourceTableInfo;
import cn.sc.summer.constant.mybatisplus.datasource.TableColumnParam;
import cn.sc.summer.constant.mybatisplus.datasource.TableInfo;
import cn.sc.summer.constant.mybatisplus.datasource.TableInfoParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 类名：数据库信息解析
 *
 * @author a-xin
 * @date 2024/8/27 13:49
 */
@Slf4j
public abstract class TableInfoService implements DataSourceTableInfo {

    private static final long serialVersionUID = -3589690871971330033L;

    /**
     * 执行查询语句
     *
     * @param jdbcTemplate 数据源代理
     * @param sql          执行sql
     * @return 查询结果
     */
    protected List<Map<String, Object>> querySql(JdbcTemplate jdbcTemplate, String sql) {
        return jdbcTemplate.queryForList(sql);
    }

    /**
     * 获取所有表信息
     *
     * @param jdbcTemplate 数据源代理
     * @return 查询结果
     */
    protected List<Map<String, Object>> queryTableInfo(JdbcTemplate jdbcTemplate) {
        return querySql(jdbcTemplate, TableResource.SQL_INFO.get(this.getSupports()).getTableInfoSql());
    }

    /**
     * 获取所有表字段信息
     *
     * @param jdbcTemplate 数据源代理
     * @return 查询结果
     */
    protected List<Map<String, Object>> queryColumnInfo(JdbcTemplate jdbcTemplate) {
        return querySql(jdbcTemplate, TableResource.SQL_INFO.get(this.getSupports()).getTableColumnSql());
    }

    /**
     * 获取指定数据源所有表主键信息
     *
     * @param jdbcTemplate 连接对象
     * @return 数据库表名对应的主键名称
     */
    public Map<String, List<String>> getTablePrimary(JdbcTemplate jdbcTemplate) {
        List<Map<String, Object>> tablePrimaryMaps = querySql(jdbcTemplate, TableResource.SQL_INFO.get(this.getSupports()).getTablePrimarySql());
        Map<String, List<String>> tablePrimaryInfoMap = new HashMap<>();
        if (CollUtil.isNotEmpty(tablePrimaryMaps)) {
            tablePrimaryMaps.stream().forEach(tablePrimary -> {
                String tableName = tablePrimary.getOrDefault(TableColumnConstant.TABLE_NAME, "").toString();
                List<String> primaryKeys = tablePrimaryInfoMap.getOrDefault(tableName, new ArrayList<>());
                String columnName = tablePrimary.getOrDefault(TableColumnConstant.COLUMN_NAME, "").toString();
                primaryKeys.add(columnName);
                tablePrimaryInfoMap.put(tableName, primaryKeys);
            });
        }
        return tablePrimaryInfoMap;
    }

    /**
     * 获取指定数据源的所有表信息
     *
     * @param jdbcTemplate 连接对象
     * @return 数据库表信息
     */
    public List<TableInfoParam> getTableInfo(JdbcTemplate jdbcTemplate) {
        List<Map<String, Object>> tableMaps = queryTableInfo(jdbcTemplate);
        List<TableInfoParam> tableInfoParams = new ArrayList<>();
        if (CollUtil.isNotEmpty(tableMaps)) {
            tableInfoParams.addAll(tableMaps.stream().map(table -> {
                TableInfoParam tableInfoParam = new TableInfoParam();
                tableInfoParam.setTableComment(table.getOrDefault(TableColumnConstant.TABLE_COMMENT, "").toString());
                tableInfoParam.setTableName(table.getOrDefault(TableColumnConstant.TABLE_NAME, "").toString());
                tableInfoParam.setTableSchema(table.getOrDefault(TableColumnConstant.TABLE_SCHEMA, "").toString());
                return tableInfoParam;
            }).collect(Collectors.toList()));
        }
        return tableInfoParams;
    }

    /**
     * 获取指定数据源中表格的数据信息，如果表格为空，则返回所有表字段信息
     *
     * @param jdbcTemplate 连接对象
     * @return 数据库表字段信息
     */
    public abstract List<TableInfo> getColumnInfo(JdbcTemplate jdbcTemplate);

    /**
     * 解析查询的表格字段信息
     *
     * @param tableDetailMaps 查询的表格字段信息
     * @return 封装对象
     */
    protected List<TableColumnParam> getTableDetail(List<Map<String, Object>> tableDetailMaps) {
        return tableDetailMaps.stream().map(tableDetailMap -> {
            TableColumnParam tableColumnParam = new TableColumnParam();

            tableColumnParam.setTableName(tableDetailMap.getOrDefault(TableColumnConstant.TABLE_NAME, "null").toString());
            tableColumnParam.setTableSchema(tableDetailMap.getOrDefault(TableColumnConstant.TABLE_SCHEMA, "null").toString());

            tableColumnParam.setColumnName(tableDetailMap.getOrDefault(TableColumnConstant.COLUMN_NAME, "null").toString());
            tableColumnParam.setColumnDefault(tableDetailMap.getOrDefault(TableColumnConstant.COLUMN_DEFAULT, "").toString());
            tableColumnParam.setNullAble(tableDetailMap.getOrDefault(TableColumnConstant.COLUMN_NULLABLE, "YES").toString());
            tableColumnParam.setDataType(tableDetailMap.getOrDefault(TableColumnConstant.COLUMN_DATA_TYPE, "null").toString());
            tableColumnParam.setMaxLength(tableDetailMap.getOrDefault(TableColumnConstant.COLUMN_LENGTH, "255").toString());
            tableColumnParam.setColumnType(tableDetailMap.getOrDefault(TableColumnConstant.COLUMN_TYPE, "null").toString());
            tableColumnParam.setColumnComment(tableDetailMap.getOrDefault(TableColumnConstant.COLUMN_COMMENT, "").toString());
            return tableColumnParam;
        }).collect(Collectors.toList());
    }

}
